package cn.iocoder.yudao.module.system.service.social.authrequest;

import cn.hutool.core.util.ReflectUtil;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.request.AlipaySystemOauthTokenRequest;
import com.alipay.api.request.AlipayUserInfoShareRequest;
import com.alipay.api.response.AlipaySystemOauthTokenResponse;
import com.alipay.api.response.AlipayUserInfoShareResponse;
import com.xingyuv.jushauth.cache.AuthStateCache;
import com.xingyuv.jushauth.config.AuthConfig;
import com.xingyuv.jushauth.enums.AuthUserGender;
import com.xingyuv.jushauth.exception.AuthException;
import com.xingyuv.jushauth.model.AuthCallback;
import com.xingyuv.jushauth.model.AuthToken;
import com.xingyuv.jushauth.model.AuthUser;
import com.xingyuv.jushauth.request.AuthAlipayRequest;
import com.xingyuv.jushauth.utils.StringUtils;

/**
 * Description:
 * Author: li
 * Date: 2024/2/28
 */
public class AuthAlipayRequestV2 extends AuthAlipayRequest {
    public AuthAlipayRequestV2(AuthConfig config) {
        super(config);
    }

    public AuthAlipayRequestV2(AuthConfig config, AuthStateCache authStateCache) {
        super(config, authStateCache);
    }

    public AuthAlipayRequestV2(AuthConfig config, AuthStateCache authStateCache, String proxyHost, Integer proxyPort) {
        super(config, authStateCache, proxyHost, proxyPort);
    }

    public AuthAlipayRequestV2(AuthConfig config, String alipayPublicKey) {
        super(config, alipayPublicKey);
    }

    public AuthAlipayRequestV2(AuthConfig config, String alipayPublicKey, AuthStateCache authStateCache) {
        super(config, alipayPublicKey, authStateCache);
    }

    public AuthAlipayRequestV2(AuthConfig config, String alipayPublicKey, AuthStateCache authStateCache, String proxyHost, Integer proxyPort) {
        super(config, alipayPublicKey, authStateCache, proxyHost, proxyPort);
    }

    @Override
    protected AuthToken getAccessToken(AuthCallback authCallback) {
        final AlipayClient alipayClient = getAlipayClient();

        AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();
        request.setGrantType("authorization_code");
        request.setCode(authCallback.getAuth_code());
        AlipaySystemOauthTokenResponse response;
        try {
            response = alipayClient.execute(request);
        } catch (Exception e) {
            throw new AuthException(e);
        }
        if (!response.isSuccess()) {
            throw new AuthException(response.getSubMsg());
        }
        return AuthToken.builder()
                .accessToken(response.getAccessToken())
                .uid(response.getUserId())
                .openId(response.getOpenId()) // 支付宝的openid
                .expireIn(Integer.parseInt(response.getExpiresIn()))
                .refreshToken(response.getRefreshToken())
                .build();
    }

    @Override
    protected AuthUser getUserInfo(AuthToken authToken) {
        final AlipayClient alipayClient = getAlipayClient();

        String accessToken = authToken.getAccessToken();
        AlipayUserInfoShareRequest request = new AlipayUserInfoShareRequest();
        AlipayUserInfoShareResponse response = null;
        try {
            response = alipayClient.execute(request, accessToken);
        } catch (AlipayApiException e) {
            throw new AuthException(e.getErrMsg(), e);
        }
        if (!response.isSuccess()) {
            throw new AuthException(response.getSubMsg());
        }

        String province = response.getProvince(), city = response.getCity();
        String location = String.format("%s %s", StringUtils.isEmpty(province) ? "" : province, StringUtils.isEmpty(city) ? "" : city);

        return AuthUser.builder()
                .rawUserInfo(JSONObject.parseObject(JSONObject.toJSONString(response)))
                .uuid(response.getOpenId()) // 支付宝的openid
                .username(StringUtils.isEmpty(response.getUserName()) ? response.getNickName() : response.getUserName())
                .nickname(response.getNickName())
                .avatar(response.getAvatar())
                .location(location)
                .gender(AuthUserGender.getRealGender(response.getGender()))
                .token(authToken)
                .source(source.toString())
                .build();
    }

    private AlipayClient getAlipayClient() {
        // 反射父类的private字段alipayClient
        final AlipayClient alipayClient = (AlipayClient) ReflectUtil.getFieldValue(this, "alipayClient");
        return alipayClient;
    }
}
